#pragma once
#include "tcp_socket.hpp"
#include <functional>

typedef std::function<void(const std::string rep, std::string* resp)> Handler;

class TcpServer
{
public:
    TcpServer(const std::string& ip, uint16_t port):ip_(ip),port_(port){}
    bool Start(Handler handler)
    {
        CHECK_RET(listen_sock.Socket());
        CHECK_RET(listen_sock.Bind(ip_, port_));
        CHECK_RET(listen_sock.Listen(5));
        for(;;)
        {
            TcpSocket new_sock;
            std::string ip;
            uint16_t port = 0;
            if(!listen_sock.Accept(&new_sock, &ip, &port))
            {
                continue;
            }
            printf("[client %s:%d] connect!", ip.c_str(), port);
            for(;;)
            {
                std::string rep;
                bool ret = new_sock.Recv(&rep);
                if(!ret)
                {
                    printf("[client %s:%d] disconnect!", ip.c_str(), port);
                    new_sock.Close();
                    break;
                }
                std::string resp;
                handler(rep, &resp);
                new_sock.Send(resp);
                printf("[%s:%d] rep:%s, resp:%s \n",ip.c_str(), port, rep.c_str(), resp.c_str());
            }
        }
        return true;
    }
private:
    TcpSocket listen_sock;
    std::string ip_;
    uint64_t port_;
};
